/* testP61A_nopack() */
/* testP61A_pack () */
/* Rip_P61A() */
/* Depack_P61A() */


#include "globals.h"



short testP61A_nopack()
{
    if (PW_i < 7)
    {
        return BAD;
    }
    PW_Start_Address = PW_i - 7;

    /* number of pattern (real) */
    PW_m = in_data[PW_Start_Address + 2];
    if ((PW_m > 0x7f) || (PW_m == 0))
    {
        /*printf ( "#1 Start:%ld\n" , PW_Start_Address );*/
        return BAD;
    }
    /* PW_m is the real number of pattern */

    /* number of sample */
    PW_k = (in_data[PW_Start_Address + 3] & 0x3F);
    if ((PW_k > 0x1F) || (PW_k == 0) || ((PW_k * 6 + PW_Start_Address + 7) >= PW_in_size))
    {
        /*printf ( "#2 Start:%ld\n" , PW_Start_Address );*/
        return BAD;
    }
    /* PW_k is the number of sample */

    /* test volumes */
    for (PW_l = 0; PW_l < PW_k; PW_l++)
    {
        if (in_data[PW_Start_Address + 7 + PW_l * 6] > 0x40)
        {
            /*printf ( "#3 Start:%ld\n" , PW_Start_Address );*/
            return BAD;
        }
    }

    /* test fines */
    for (PW_l = 0; PW_l < PW_k; PW_l++)
    {
        if (in_data[PW_Start_Address + 6 + PW_l * 6] > 0x0F)
        {
            /*printf ( "#4 Start:%ld\n" , PW_Start_Address );*/
            return BAD;
        }
    }

    /* test sample sizes and loop start */
    PW_WholeSampleSize = 0;
    for (PW_n = 0; PW_n < PW_k; PW_n++)
    {
        PW_o = ((in_data[PW_Start_Address + 4 + PW_n * 6] * 256) +
                in_data[PW_Start_Address + 5 + PW_n * 6]);
        if (((PW_o < 0xFFDF) && (PW_o > 0x8000)) || (PW_o == 0))
        {
            /*printf ( "#5 Start:%ld\n" , PW_Start_Address );*/
            return BAD;
        }
        if (PW_o < 0xFF00)
            PW_WholeSampleSize += (PW_o * 2);

        PW_j = ((in_data[PW_Start_Address + 8 + PW_n * 6] * 256) +
                in_data[PW_Start_Address + 9 + PW_n * 6]);
        if ((PW_j != 0xFFFF) && (PW_j >= PW_o))
        {
            /*printf ( "#5,1 Start:%ld\n" , PW_Start_Address );*/
            return BAD;
        }
        if (PW_o > 0xFFDF)
        {
            if ((0xFFFF - PW_o) > PW_k)
            {
                /*printf ( "#5,2 Start:%ld\n" , PW_Start_Address );*/
                return BAD;
            }
        }
    }

    /* test sample data address */
    PW_j = (in_data[PW_Start_Address] * 256) + in_data[PW_Start_Address + 1];
    if (PW_j < (PW_k * 6 + 4 + PW_m * 8))
    {
        /*printf ( "#6 Start:%ld\n" , PW_Start_Address );*/
        return BAD;
    }
    /* PW_j is the address of the sample data */


    /* test track table */
    for (PW_l = 0; PW_l < (PW_m * 4); PW_l++)
    {
        PW_o = ((in_data[PW_Start_Address + 4 + PW_k * 6 + PW_l * 2] * 256) +
                in_data[PW_Start_Address + 4 + PW_k * 6 + PW_l * 2 + 1]);
        if ((PW_o + PW_k * 6 + 4 + PW_m * 8) > PW_j)
        {
            /*printf ( "#7 Start:%ld (value:%ld)(where:%x)(PW_l:%ld)(PW_m:%ld)(PW_o:%ld)\n"
               , PW_Start_Address
               , (in_data[PW_Start_Address+PW_k*6+4+PW_l*2]*256)+in_data[PW_Start_Address+4+PW_k*6+PW_l*2+1]
               , PW_Start_Address+PW_k*6+4+PW_l*2
               , PW_l
               , PW_m
               , PW_o );*/
            return BAD;
        }
    }

    /* test pattern table */
    PW_l = 0;
    PW_o = 0;
    /* first, test if we dont oversize the input file */
    if ((PW_Start_Address + PW_k * 6 + 4 + PW_m * 8) > PW_in_size)
    {
        /*printf ( "8,0 Start:%ld\n" , PW_Start_Address );*/
        return BAD;
    }
    while ((in_data[PW_Start_Address + PW_k * 6 + 4 + PW_m * 8 + PW_l] != 0xFF) && (PW_l < 128))
    {
        if (in_data[PW_Start_Address + PW_k * 6 + 4 + PW_m * 8 + PW_l] > (PW_m - 1))
        {
            /*printf ( "#8,1 Start:%ld (value:%ld)(where:%x)(PW_l:%ld)(PW_m:%ld)(PW_k:%ld)\n"
               , PW_Start_Address
               , in_data[PW_Start_Address+PW_k*6+4+PW_m*8+PW_l]
               , PW_Start_Address+PW_k*6+4+PW_m*8+PW_l
               , PW_l
               , PW_m
               , PW_k );*/
            return BAD;
        }
        if (in_data[PW_Start_Address + PW_k * 6 + 4 + PW_m * 8 + PW_l] > PW_o)
            PW_o = in_data[PW_Start_Address + PW_k * 6 + 4 + PW_m * 8 + PW_l];
        PW_l++;
    }
    /* are we beside the sample data address ? */
    if ((PW_k * 6 + 4 + PW_m * 8 + PW_l) > PW_j)
    {
        return BAD;
    }
    if ((PW_l == 0) || (PW_l == 128))
    {
        /*printf ( "#8.2 Start:%ld\n" , PW_Start_Address );*/
        return BAD;
    }
    PW_o += 1;
    /* PW_o is the highest number of pattern */


    /* test notes ... pfiew */
    PW_l += 1;
    for (PW_n = (PW_k * 6 + 4 + PW_m * 8 + PW_l); PW_n < PW_j; PW_n++)
    {
        if ((in_data[PW_Start_Address + PW_n] & 0xff) == 0xff)
        {
            if ((in_data[PW_Start_Address + PW_n + 1] & 0xc0) == 0x00)
            {
                PW_n += 1;
                continue;
            }
            if ((in_data[PW_Start_Address + PW_n + 1] & 0xc0) == 0x40)
            {
                PW_n += 2;
                continue;
            }
            if ((in_data[PW_Start_Address + PW_n + 1] & 0xc0) == 0xc0)
            {
                if (PW_n < ((in_data[PW_Start_Address + PW_n + 2] * 256) + in_data[PW_Start_Address + PW_n + 3] - 1))
                    return BAD;
                PW_n += 3;
                continue;
            }
        }
        if ((in_data[PW_Start_Address + PW_n] & 0xff) == 0x7f)
        {
            continue;
        }

        /* no Fx nor FxArg */
        if ((in_data[PW_Start_Address + PW_n] & 0xf0) == 0xf0)
        {
            if ((in_data[PW_Start_Address + PW_n + 1] & 0x1F) > PW_k)
            {
                /*printf ( "#9,1 Start:%ld (value:%ld) (where:%x) (PW_n:%ld) (PW_j:%ld)\n"
                   , PW_Start_Address
                   , in_data[PW_Start_Address+PW_n]
                   , PW_Start_Address+PW_n
                   , PW_n
                   , PW_j
                   );*/
                return BAD;
            }
            PW_n += 2;
            continue;
        }
        if ((in_data[PW_Start_Address + PW_n] & 0xf0) == 0x70)
        {
            if ((in_data[PW_Start_Address + PW_n + 1] & 0x1F) > PW_k)
            {
                /*printf ( "#9,2 Start:%ld (value:%ld) (where:%x) (PW_n:%ld) (PW_j:%ld)\n"
                   , PW_Start_Address
                   , in_data[PW_Start_Address+PW_n]
                   , PW_Start_Address+PW_n
                   , PW_n
                   , PW_j
                   );*/
                return BAD;
            }
            PW_n += 1;
            continue;
        }
        /* no Note nor Sample number */
        if ((in_data[PW_Start_Address + PW_n] & 0xf0) == 0xe0)
        {
            PW_n += 2;
            continue;
        }
        if ((in_data[PW_Start_Address + PW_n] & 0xf0) == 0x60)
        {
            PW_n += 1;
            continue;
        }

        if ((in_data[PW_Start_Address + PW_n] & 0x80) == 0x80)
        {
            if ((((in_data[PW_Start_Address + PW_n] << 4) & 0x10) | ((in_data[PW_Start_Address + PW_n + 1] >> 4) & 0x0F)) > PW_k)
            {
                /*printf ( "#9,3 Start:%ld (value:%ld) (where:%x) (PW_n:%ld) (PW_j:%ld)\n"
                   , PW_Start_Address
                   , in_data[PW_Start_Address+PW_n]
                   , PW_Start_Address+PW_n
                   , PW_n
                   , PW_j
                   );*/
                return BAD;
            }
            PW_n += 3;
            continue;
        }

        if ((((in_data[PW_Start_Address + PW_n] << 4) & 0x10) | ((in_data[PW_Start_Address + PW_n + 1] >> 4) & 0x0F)) > PW_k)
        {
            /*printf ( "#9,4 Start:%ld (value:%ld) (where:%x) (PW_n:%ld) (PW_j:%ld)\n"
               , PW_Start_Address
               , in_data[PW_Start_Address+PW_n]
               , PW_Start_Address+PW_n
               , PW_n
               , PW_j
               );*/
            return BAD;
        }
        PW_n += 2;
    }

    /* PW_WholeSampleSize is the whole sample data size */
    /* PW_j is the address of the sample data */
    return GOOD;
}


/******************/
/* packed samples */
/******************/
short testP61A_pack()
{
    if (PW_i < 11)
    {
        return BAD;
    }
    PW_Start_Address = PW_i - 11;

    /* number of pattern (real) */
    PW_m = in_data[PW_Start_Address + 2];
    if ((PW_m > 0x7f) || (PW_m == 0))
    {
        /*printf ( "#1 Start:%ld\n" , PW_Start_Address );*/
        return BAD;
    }
    /* PW_m is the real number of pattern */

    /* number of sample */
    PW_k = in_data[PW_Start_Address + 3];
    if ((PW_k & 0x40) != 0x40)
    {
        /*printf ( "#2,0 Start:%ld\n" , PW_Start_Address );*/
        return BAD;
    }
    PW_k &= 0x3F;
    if ((PW_k > 0x1F) || (PW_k == 0))
    {
        /*printf ( "#2,1 Start:%ld (PW_k:%ld)\n" , PW_Start_Address,PW_k );*/
        return BAD;
    }
    /* PW_k is the number of sample */

    /* test volumes */
    if ((PW_Start_Address + 11 + (PW_k * 6)) > PW_in_size)
        return BAD;
    for (PW_l = 0; PW_l < PW_k; PW_l++)
    {
        if (in_data[PW_Start_Address + 11 + PW_l * 6] > 0x40)
        {
            /*printf ( "#3 Start:%ld\n" , PW_Start_Address );*/
            return BAD;
        }
    }

    /* test fines */
    for (PW_l = 0; PW_l < PW_k; PW_l++)
    {
        if ((in_data[PW_Start_Address + 10 + PW_l * 6] & 0x3F) > 0x0F)
        {
            /*printf ( "#4 Start:%ld\n" , PW_Start_Address );*/
            return BAD;
        }
    }

    /* test sample sizes and loop start */
    PW_WholeSampleSize = 0;
    for (PW_n = 0; PW_n < PW_k; PW_n++)
    {
        PW_o = ((in_data[PW_Start_Address + 8 + PW_n * 6] * 256) +
                in_data[PW_Start_Address + 9 + PW_n * 6]);
        if (((PW_o < 0xFFDF) && (PW_o > 0x8000)) || (PW_o == 0))
        {
            /*printf ( "#5 Start:%ld\n" , PW_Start_Address );*/
            return BAD;
        }
        if (PW_o < 0xFF00)
            PW_WholeSampleSize += (PW_o * 2);

        PW_j = ((in_data[PW_Start_Address + 12 + PW_n * 6] * 256) +
                in_data[PW_Start_Address + 13 + PW_n * 6]);
        if ((PW_j != 0xFFFF) && (PW_j >= PW_o))
        {
            /*printf ( "#5,1 Start:%ld\n" , PW_Start_Address );*/
            return BAD;
        }
        if (PW_o > 0xFFDF)
        {
            if ((0xFFFF - PW_o) > PW_k)
            {
                /*printf ( "#5,2 Start:%ld\n" , PW_Start_Address );*/
                return BAD;
            }
        }
    }

    /* test sample data address */
    PW_j = (in_data[PW_Start_Address] * 256) + in_data[PW_Start_Address + 1];
    if (PW_j < (PW_k * 6 + 8 + PW_m * 8))
    {
        /*printf ( "#6 Start:%ld\n" , PW_Start_Address );*/
        return BAD;
    }
    /* PW_j is the address of the sample data */


    /* test track table */
    for (PW_l = 0; PW_l < (PW_m * 4); PW_l++)
    {
        PW_o = ((in_data[PW_Start_Address + 8 + PW_k * 6 + PW_l * 2] * 256) +
                in_data[PW_Start_Address + 8 + PW_k * 6 + PW_l * 2 + 1]);
        if ((PW_o + PW_k * 6 + 8 + PW_m * 8) > PW_j)
        {
            /*printf ( "#7 Start:%ld (value:%ld)(where:%x)(PW_l:%ld)(PW_m:%ld)(PW_o:%ld)\n"
               , PW_Start_Address
               , (in_data[PW_Start_Address+PW_k*6+8+PW_l*2]*256)+in_data[PW_Start_Address+8+PW_k*6+PW_l*2+1]
               , PW_Start_Address+PW_k*6+8+PW_l*2
               , PW_l
               , PW_m
               , PW_o );*/
            return BAD;
        }
    }

    /* test pattern table */
    PW_l = 0;
    PW_o = 0;
    /* first, test if we dont oversize the input file */
    if ((PW_k * 6 + 8 + PW_m * 8) > PW_in_size)
    {
        /*printf ( "8,0 Start:%ld\n" , PW_Start_Address );*/
        return BAD;
    }
    while ((in_data[PW_Start_Address + PW_k * 6 + 8 + PW_m * 8 + PW_l] != 0xFF) && (PW_l < 128))
    {
        if (in_data[PW_Start_Address + PW_k * 6 + 8 + PW_m * 8 + PW_l] > (PW_m - 1))
        {
            /*printf ( "#8,1 Start:%ld (value:%ld)(where:%x)(PW_l:%ld)(PW_m:%ld)(PW_k:%ld)\n"
               , PW_Start_Address
               , in_data[PW_Start_Address+PW_k*6+8+PW_m*8+PW_l]
               , PW_Start_Address+PW_k*6+8+PW_m*8+PW_l
               , PW_l
               , PW_m
               , PW_k );*/
            return BAD;
        }
        if (in_data[PW_Start_Address + PW_k * 6 + 8 + PW_m * 8 + PW_l] > PW_o)
            PW_o = in_data[PW_Start_Address + PW_k * 6 + 8 + PW_m * 8 + PW_l];
        PW_l++;
    }
    if ((PW_l == 0) || (PW_l == 128))
    {
        /*printf ( "#8.2 Start:%ld\n" , PW_Start_Address );*/
        return BAD;
    }
    PW_o += 1;
    /* PW_o is the highest number of pattern */


    /* test notes ... pfiew */
    PW_l += 1;
    for (PW_n = (PW_k * 6 + 8 + PW_m * 8 + PW_l); PW_n < PW_j; PW_n++)
    {
        if ((in_data[PW_Start_Address + PW_n] & 0xff) == 0xff)
        {
            if ((in_data[PW_Start_Address + PW_n + 1] & 0xc0) == 0x00)
            {
                PW_n += 1;
                continue;
            }
            if ((in_data[PW_Start_Address + PW_n + 1] & 0xc0) == 0x40)
            {
                PW_n += 2;
                continue;
            }
            if ((in_data[PW_Start_Address + PW_n + 1] & 0xc0) == 0xc0)
            {
                PW_n += 3;
                continue;
            }
        }
        if ((in_data[PW_Start_Address + PW_n] & 0xff) == 0x7f)
        {
            continue;
        }

        /* no Fx nor FxArg */
        if ((in_data[PW_Start_Address + PW_n] & 0xf0) == 0xf0)
        {
            if ((in_data[PW_Start_Address + PW_n + 1] & 0x1F) > PW_k)
            {
                /*printf ( "#9,1 Start:%ld (value:%ld) (where:%x) (PW_n:%ld) (PW_j:%ld)\n"
                   , PW_Start_Address
                   , in_data[PW_Start_Address+PW_n]
                   , PW_Start_Address+PW_n
                   , PW_n
                   , PW_j
                   );*/
                return BAD;
            }
            PW_n += 2;
            continue;
        }
        if ((in_data[PW_Start_Address + PW_n] & 0xf0) == 0x70)
        {
            if ((in_data[PW_Start_Address + PW_n + 1] & 0x1F) > PW_k)
            {
                /*printf ( "#9,1 Start:%ld (value:%ld) (where:%x) (PW_n:%ld) (PW_j:%ld)\n"
                   , PW_Start_Address
                   , in_data[PW_Start_Address+PW_n]
                   , PW_Start_Address+PW_n
                   , PW_n
                   , PW_j
                   );*/
                return BAD;
            }
            PW_n += 1;
            continue;
        }
        /* no Note nor Sample number */
        if ((in_data[PW_Start_Address + PW_n] & 0xf0) == 0xe0)
        {
            PW_n += 2;
            continue;
        }
        if ((in_data[PW_Start_Address + PW_n] & 0xf0) == 0x60)
        {
            PW_n += 1;
            continue;
        }

        if ((in_data[PW_Start_Address + PW_n] & 0x80) == 0x80)
        {
            if ((((in_data[PW_Start_Address + PW_n] << 4) & 0x10) | ((in_data[PW_Start_Address + PW_n + 1] >> 4) & 0x0F)) > PW_k)
            {
                /*printf ( "#9,1 Start:%ld (value:%ld) (where:%x) (PW_n:%ld) (PW_j:%ld)\n"
                   , PW_Start_Address
                   , in_data[PW_Start_Address+PW_n]
                   , PW_Start_Address+PW_n
                   , PW_n
                   , PW_j
                   );*/
                return BAD;
            }
            PW_n += 3;
            continue;
        }

        if ((((in_data[PW_Start_Address + PW_n] << 4) & 0x10) | ((in_data[PW_Start_Address + PW_n + 1] >> 4) & 0x0F)) > PW_k)
        {
            /*printf ( "#9,1 Start:%ld (value:%ld) (where:%x) (PW_n:%ld) (PW_j:%ld)\n"
               , PW_Start_Address
               , in_data[PW_Start_Address+PW_n]
               , PW_Start_Address+PW_n
               , PW_n
               , PW_j
               );*/
            return BAD;
        }
        PW_n += 2;
    }


    /* PW_WholeSampleSize is the whole sample data size */
    /* PW_j is the address of the sample data */
    return GOOD;
}



void Rip_P61A()
{
    /* PW_j is the number of sample */
    /* PW_WholeSampleSize is the whole sample data size */

    OutputSize = PW_j + PW_WholeSampleSize;

    CONVERT = GOOD;
    Save_Rip("The Player 6.1A module", P61A);

    if (Save_Status == GOOD)
        PW_i += 12; /* 7 should do but call it "just to be sure" :) */
}



/*
 *   The_Player_6.1a.c   1998 (c) Asle / ReDoX
 *
 * The Player 6.1a to Protracker.
 *
 * Note: As for version 5.0A and 6.0A, it's a REAL mess !.
 *      It's VERY badly coded, I know. Just dont forget it was mainly done
 *      to test the description I made of P61a format.
 *      I certainly wont dare to beat Gryzor on the ground :). His Prowiz IS
 *      the converter to use !!!. Though, using the official depacker could
 *      be a good idea too :).
 *
 * update:28/11/99
 *   - removed fopen() and all similar functions
 *   - Speed and Size (?) optimizings
 *
 * update:03/04/00
 *   - some code went away ????. reput it back :)
 *     pointed out by Thomas Neumann .. thx
 * update:26 nov 2003
 *   - used htonl() so that use of addy is now portable on 68k archs
 */

#define ON 1
#define OFF 2

void Depack_P61A()
{
    Uchar c1, c2, c3, c4, c5, c6;
    long Max;
    Uchar* Whatever;
    signed char* SmpDataWork;
    Uchar PatPos = 0x00;
    Uchar PatMax = 0x00;
    Uchar Nbr_Sample = 0x00;
    Uchar poss[37][2];
    Uchar Track_Data[512][256];
    Uchar SmpSizes[31][2];
    Uchar PACK[31];
    /*  Uchar DELTA[31];*/
    Uchar GLOBAL_DELTA = OFF;
    Uchar GLOBAL_PACK = OFF;
    long Track_Address[128][4];
    long Track_Data_Address = 0;
    long Sample_Data_Address = 0;
    long WholeSampleSize = 0;
    long i = 0, j, k, l, a, b, z, w;
    long SampleSizes[31];
    long SampleAddresses[32];
    long Unpacked_Sample_Data_Size;
    long Where = PW_Start_Address;
    FILE* out;

    if (Save_Status == BAD)
        return;

    BZERO(Track_Address, 128 * 4 * 4);
    BZERO(Track_Data, 512 * 256);
    BZERO(SampleSizes, 31 * 4);
    BZERO(SampleAddresses, 32 * 4);
    BZERO(SmpSizes, 31 * 2);
    for (i = 0; i < 31; i++)
    {
        PACK[i] = OFF;
        /*    DELTA[i] = OFF;*/
    }

    fillPTKtable(poss);

    sprintf(Depacked_OutName, "%ld.mod", Cpt_Filename - 1);
    out = PW_fopen(Depacked_OutName, "w+b");

    /* read sample data address */
    Sample_Data_Address = (in_data[Where] * 256) + in_data[Where + 1];
    Where += 2;

    /* read Real number of pattern */
    PatMax = in_data[Where++];

    /* read number of samples */
    Nbr_Sample = in_data[Where++];
    if ((Nbr_Sample & 0x80) == 0x80)
    {
        /*printf ( "Samples are saved as delta values !\n" );*/
        GLOBAL_DELTA = ON;
    }
    if ((Nbr_Sample & 0x40) == 0x40)
    {
        /*printf ( "some samples are packed !\n" );*/
        /*printf ( "\n! Since I could not understand the packing method of the\n"*/
        /*         "! samples, neither could I do a depacker .. . mission ends here :)\n" );*/
        GLOBAL_PACK = ON;
        return;
    }
    Nbr_Sample &= 0x3F;

    /* read unpacked sample data size */
    if (GLOBAL_PACK == ON)
    {
        Unpacked_Sample_Data_Size = (in_data[Where] * 256 * 256 * 256) +
                                    (in_data[Where] * 256 * 256) +
                                    (in_data[Where] * 256) +
                                    in_data[Where];
    }

    /* write title */
    Whatever = (Uchar*)malloc(1024);
    BZERO(Whatever, 1024);
    fwrite(Whatever, 20, 1, out);

    /* sample headers stuff */
    for (i = 0; i < Nbr_Sample; i++)
    {
        /* write sample name */
        fwrite(Whatever, 22, 1, out);

        /* sample size */
        SmpSizes[i][0] = in_data[Where];
        SmpSizes[i][1] = in_data[Where + 1];
        j = (SmpSizes[i][0] * 256) + SmpSizes[i][1];
        if (j > 0xFF00)
        {
            SampleSizes[i] = SampleSizes[0xFFFF - j];
            SmpSizes[i][0] = SmpSizes[0xFFFF - j][0];
            SmpSizes[i][1] = SmpSizes[0xFFFF - j][1];
            /*fprintf ( debug , "!%2ld!" , 0xFFFF-j );*/
            SampleAddresses[i + 1] = SampleAddresses[0xFFFF - j + 1]; /* - SampleSizes[i]+SampleSizes[0xFFFF-j];*/
        }
        else
        {
            SampleAddresses[i + 1] = SampleAddresses[i] + SampleSizes[i - 1];
            SampleSizes[i] = j * 2;
            WholeSampleSize += SampleSizes[i];
        }
        j = SampleSizes[i] / 2;
        fwrite(&SmpSizes[i][0], 1, 1, out);
        fwrite(&SmpSizes[i][1], 1, 1, out);

        /* finetune */
        c1 = in_data[Where + 2];
        if ((c1 & 0x40) == 0x40)
            PACK[i] = ON;
        c1 &= 0x3F;
        fwrite(&c1, 1, 1, out);

        /* vol */
        fwrite(&in_data[Where + 3], 1, 1, out);

        /* loop start */
        /*fprintf ( debug , "loop start : %2x, %2x " , c1,c2 );*/
        if ((in_data[Where + 4] == 0xFF) && (in_data[Where + 5] == 0xFF))
        {
            Whatever[53] = 0x01;
            fwrite(&Whatever[50], 4, 1, out);
            /*fprintf ( debug , " <--- no loop! (%2x,%2x)\n" ,c3,c4);*/
            Where += 6;
            continue;
        }
        fwrite(&in_data[Where + 4], 2, 1, out);
        l = j - ((in_data[Where + 4] * 256) + in_data[Where + 5]);
        /*fprintf ( debug , " -> size:%6ld  lstart:%5d  -> lsize:%ld\n" , j,c1*256+c2,l );*/

        /* use of htonl() suggested by Xigh !.*/
        w = htonl(l);
        c1 = *((Uchar*)&w + 2);
        c2 = *((Uchar*)&w + 3);
        fwrite(&c1, 1, 1, out);
        fwrite(&c2, 1, 1, out);

        Where += 6;
    }

    /* go up to 31 samples */
    Whatever[129] = 0x01;
    while (i != 31)
    {
        fwrite(&Whatever[100], 30, 1, out);
        i += 1;
    }
    /*printf ( "Whole sample size : %ld\n" , WholeSampleSize );*/

    /*fprintf ( debug , "Where after sample headers : %x\n" , ftell ( in ) );*/

    /* read tracks addresses per pattern */
    for (i = 0; i < PatMax; i++)
    {
        /*fprintf ( debug , "\npattern %ld : " , i );*/
        for (j = 0; j < 4; j++)
        {
            Track_Address[i][j] = (in_data[Where] * 256) + in_data[Where + 1];
            Where += 2;
            /*fprintf ( debug , "%6ld, " , Track_Address[i][j] );*/
        }
    }
    /*fprintf ( debug , "\n\nwhere after the track addresses : %x\n\n" , ftell ( in ));*/


    /* pattern table */
    /*fprintf ( debug , "\nPattern table :\n" );*/
    BZERO(Whatever, 1024);
    for (PatPos = 0; PatPos < 128; PatPos++)
    {
        c1 = in_data[Where++];
        if (c1 == 0xFF)
            break;
        Whatever[PatPos] = c1;
        /*fprintf ( debug , "%2x, " , Whatever[PatPos] );*/
    }

    /* write size of pattern list */
    fwrite(&PatPos, 1, 1, out);
    /*fprintf ( debug , "\nsize of the pattern table : %d\n\n" , PatPos );*/

    /* write noisetracker byte */
    c1 = 0x7f;
    fwrite(&c1, 1, 1, out);

    /* write pattern table */
    fwrite(Whatever, 128, 1, out);

    /* write ptk's ID */
    Whatever[0] = 'M';
    Whatever[1] = '.';
    Whatever[2] = 'K';
    Whatever[3] = '.';
    fwrite(Whatever, 4, 1, out);

    /*fprintf ( debug , "\n\nbefore reading track data : %x\n" , ftell ( in ) );*/
    Track_Data_Address = Where;

    /* rewrite the track data */

    /*printf ( "sorting and depacking tracks data ... " );*/
    for (i = 0; i < PatMax; i++)
    {
        /*fprintf ( debug , "\n\npattern %ld\n" , i );*/
        Max = 63;
        for (j = 0; j < 4; j++)
        {
            Where = Track_Address[i][j] + Track_Data_Address;
            /*fprintf ( debug , "track %ld (at:%ld)\n" , j,ftell ( in ) );*/
            for (k = 0; k <= Max; k++)
            {
                c1 = in_data[Where++];
                /*fprintf ( debug , "%2ld: %2x, " , k , c1 );*/

                /* case no Fx nor FxArg  (3 bytes) */
                if (((c1 & 0x70) == 0x70) && (c1 != 0xFF) && (c1 != 0x7F))
                {
                    c2 = in_data[Where++];
                    /*fprintf ( debug , "%2x, " , c2 );*/
                    c6 = ((c1 << 4) & 0xf0) | ((c2 >> 4) & 0x0e);
                    Track_Data[i * 4 + j][k * 4] = (c2 & 0x10) | (poss[c6 / 2][0]);
                    Track_Data[i * 4 + j][k * 4 + 1] = poss[c6 / 2][1];
                    Track_Data[i * 4 + j][k * 4 + 2] = ((c2 << 4) & 0xf0);

                    if ((c1 & 0x80) == 0x80)
                    {
                        c3 = in_data[Where++];
                        if (c3 < 0x80)
                        {
                            /*fprintf ( debug , "%2x  <--- bypass %d rows !\n" , c3 , c3 );*/
                            k += c3;
                            continue;
                        }
                        /*fprintf ( debug , "%2x  <--- repeat current row %d times\n" , c3 , c3-0x80 );*/
                        c4 = c3 - 0x80;
                        for (l = 0; l < c4; l++)
                        {
                            k += 1;
                            /*fprintf ( debug , "*%2ld: %2x, %2x\n" , k , c1,c2 );*/
                            Track_Data[i * 4 + j][k * 4] = (c2 & 0x10) | (poss[c6 / 2][0]);
                            Track_Data[i * 4 + j][k * 4 + 1] = poss[c6 / 2][1];
                            Track_Data[i * 4 + j][k * 4 + 2] = ((c2 << 4) & 0xf0);
                        }
                    }
                    /*fprintf ( debug , "\n" );*/
                    continue;
                }
                /* end of case no Fx nor FxArg */

                /* case no Sample number nor Relative not number */
                if (((c1 & 0x70) == 0x60) && (c1 != 0xFF))
                {
                    c2 = in_data[Where++];
                    /*fprintf ( debug , "%2x, " , c2 );*/

                    c6 = c1 & 0x0f;
                    if (c6 == 0x08)
                        c1 -= 0x08;
                    Track_Data[i * 4 + j][k * 4 + 2] = (c1 & 0x0f);
                    if ((c6 == 0x05) || (c6 == 0x06) || (c6 == 0x0a))
                        c2 = (c2 > 0x7f) ? ((0x100 - c2) << 4) : c2;
                    Track_Data[i * 4 + j][k * 4 + 3] = c2;

                    if (c6 == 0x0D)
                    {
                        /*fprintf ( debug , " <-- PATTERN BREAK !, track ends\n" );*/
                        Max = k;
                        k = 9999l;
                        continue;
                    }
                    if (c6 == 0x0B)
                    {
                        /*fprintf ( debug , " <-- PATTERN JUMP !, track ends\n" );*/
                        Max = k;
                        k = 9999l;
                        continue;
                    }
                    if ((c1 & 0x80) == 0x80)
                    {
                        c3 = in_data[Where++];
                        if (c3 < 0x80)
                        {
                            /*fprintf ( debug , "%2x  <--- bypass %d rows !\n" , c3 , c3 );*/
                            k += c3;
                            continue;
                        }
                        /*fprintf ( debug , "%2x  <--- repeat current row %d times\n" , c3 , c3-0x80 );*/
                        c4 = c3 - 0x80;
                        for (l = 0; l < c4; l++)
                        {
                            k += 1;
                            /*fprintf ( debug , "*%2ld: %2x, %2x\n" , k , c1,c2 );*/
                            Track_Data[i * 4 + j][k * 4 + 2] = (c1 & 0x0f);
                            Track_Data[i * 4 + j][k * 4 + 3] = c2;
                        }
                    }
                    /*fprintf ( debug , "\n" );*/
                    continue;
                }
                /* end of case no Sample number nor Relative not number */

                if (((c1 & 0x80) == 0x80) && (c1 != 0xFF))
                {
                    c2 = in_data[Where++];
                    c3 = in_data[Where++];
                    c4 = in_data[Where++];
                    /*fprintf ( debug , "%2x, %2x, " , c2,c3);*/
                    c1 = c1 & 0x7F;
                    Track_Data[i * 4 + j][k * 4] = ((c1 << 4) & 0x10) | (poss[c1 / 2][0]);
                    Track_Data[i * 4 + j][k * 4 + 1] = poss[c1 / 2][1];
                    c6 = c2 & 0x0f;
                    if (c6 == 0x08)
                        c2 -= 0x08;
                    Track_Data[i * 4 + j][k * 4 + 2] = c2;
                    if ((c6 == 0x05) || (c6 == 0x06) || (c6 == 0x0a))
                        c3 = (c3 > 0x7f) ? ((0x100 - c3) << 4) : c3;
                    Track_Data[i * 4 + j][k * 4 + 3] = c3;
                    if (c6 == 0x0D)
                    {
                        /*fprintf ( debug , " <-- PATTERN BREAK !, track ends\n" );*/
                        Max = k;
                        k = 9999l;
                        continue;
                    }
                    if (c6 == 0x0B)
                    {
                        /*fprintf ( debug , " <-- PATTERN JUMP !, track ends\n" );*/
                        Max = k;
                        k = 9999l;
                        continue;
                    }

                    if (c4 < 0x80)
                    {
                        /*fprintf ( debug , "%2x  <--- bypass %d rows !\n" , c4 , c4 );*/
                        k += c4;
                        continue;
                    }
                    /*fprintf ( debug , "%2x  <--- repeat current row %d times\n" , c4 , c4-0x80 );*/
                    c4 = c4 - 0x80;
                    for (l = 0; l < c4; l++)
                    {
                        k += 1;
                        /*fprintf ( debug , "*%2ld: %2x, %2x, %2x\n" , k , c1,c2,c3 );*/
                        Track_Data[i * 4 + j][k * 4] = ((c1 << 4) & 0x10) | (poss[c1 / 2][0]);
                        Track_Data[i * 4 + j][k * 4 + 1] = poss[c1 / 2][1];
                        c6 = c2 & 0x0f;
                        if (c6 == 0x08)
                            c2 -= 0x08;
                        Track_Data[i * 4 + j][k * 4 + 2] = c2;
                        if ((c6 == 0x05) || (c6 == 0x06) || (c6 == 0x0a))
                            c3 = (c3 > 0x7f) ? ((0x100 - c3) << 4) : c3;
                        Track_Data[i * 4 + j][k * 4 + 3] = c3;
                    }
                    continue;
                }


                if ((c1 & 0x7F) == 0x7F)
                {
                    if ((c1 & 0x80) == 0x00)
                    {
                        /*fprintf ( debug , "  <--- bypass 1 row !\n" );*/
                        /*k += 1;*/
                        continue;
                    }
                    c2 = in_data[Where++];
                    if (c2 < 0x40)
                    {
                        /*fprintf ( debug , "%2x  <--- bypass %d rows !\n" , c2 , c2 );*/
                        k += c2;
                        continue;
                    }
                    /*fprintf ( debug , "%2x, " , c2 );*/
                    c2 -= 0x40;
                    c3 = in_data[Where++];
                    /*fprintf ( debug , "%2x, " , c3 );*/
                    z = c3;
                    if (c2 >= 0x80)
                    {
                        c2 -= 0x80;
                        c4 = in_data[Where++];
                        /*fprintf ( debug , "%2x, " , c4 );*/
                        z = (c3 * 256) + c4;
                    }
                    /*fprintf ( debug , " <--- repeat %2d lines some %ld bytes before\n" , c2,z );*/
                    a = Where;
                    c5 = c2;
                    Where -= z;
                    for (l = 0; (l <= c5) && (k <= Max); l++, k++)
                    {
                        c1 = in_data[Where++];
                        /*fprintf ( debug , "#%2ld: %2x, " , l , c1 );*/

                        /* case no Fx nor FxArg  (3 bytes) */
                        if (((c1 & 0x70) == 0x70) && (c1 != 0xFF) && (c1 != 0x7F))
                        {
                            c2 = in_data[Where++];
                            /*fprintf ( debug , "%2x, " , c2 );*/
                            c6 = ((c1 << 4) & 0xf0) | ((c2 >> 4) & 0x0e);
                            Track_Data[i * 4 + j][k * 4] = (c2 & 0x10) | (poss[c6 / 2][0]);
                            Track_Data[i * 4 + j][k * 4 + 1] = poss[c6 / 2][1];
                            Track_Data[i * 4 + j][k * 4 + 2] = ((c2 << 4) & 0xf0);

                            if ((c1 & 0x80) == 0x80)
                            {
                                c3 = in_data[Where++];
                                if (c3 < 0x80)
                                {
                                    /*fprintf ( debug , "%2x  <--- bypass %d rows !\n" , c3 , c3 );*/
                                    k += c3;
                                    continue;
                                }
                                /*fprintf ( debug , "%2x  <--- repeat current row %d times\n" , c3 , c3-0x80 );*/
                                c4 = c3 - 0x80;
                                for (b = 0; b < c4; b++)
                                {
                                    k += 1;
                                    /*fprintf ( debug , "*%2ld: %2x, %2x\n" , k , c1,c2 );*/
                                    Track_Data[i * 4 + j][k * 4] = (c2 & 0x10) | (poss[c6 / 2][0]);
                                    Track_Data[i * 4 + j][k * 4 + 1] = poss[c6 / 2][1];
                                    Track_Data[i * 4 + j][k * 4 + 2] = ((c2 << 4) & 0xf0);
                                }
                            }
                            /*fprintf ( debug , "\n" );*/
                            continue;
                        }
                        /* end of case no Fx nor FxArg */

                        /* case no Sample number nor Relative not number */
                        if (((c1 & 0x60) == 0x60) && (c1 != 0xFF) && (c1 != 0x7F))
                        {
                            c2 = in_data[Where++];
                            /*fprintf ( debug , "%2x, " , c2 );*/
                            c6 = c1 & 0x0f;
                            if (c6 == 0x08)
                                c1 -= 0x08;
                            Track_Data[i * 4 + j][k * 4 + 2] = (c1 & 0x0f);
                            if ((c6 == 0x05) || (c6 == 0x06) || (c6 == 0x0a))
                                c2 = (c2 > 0x7f) ? ((0x100 - c2) << 4) : c2;
                            Track_Data[i * 4 + j][k * 4 + 3] = c2;

                            if (c6 == 0x0D)
                            {
                                /*fprintf ( debug , " <-- PATTERN BREAK !, track ends\n" );*/
                                Max = k;
                                k = 9999l;
                                continue;
                            }
                            if (c6 == 0x0B)
                            {
                                /*fprintf ( debug , " <-- PATTERN JUMP !, track ends\n" );*/
                                Max = k;
                                k = 9999l;
                                continue;
                            }

                            if ((c1 & 0x80) == 0x80)
                            {
                                c3 = in_data[Where++];
                                if (c3 < 0x80)
                                {
                                    /*fprintf ( debug , "%2x  <--- bypass %d rows !\n" , c3 , c3 );*/
                                    k += c3;
                                    continue;
                                }
                                /*fprintf ( debug , "%2x  <--- repeat current row %d times\n" , c3 , c3-0x80 );*/
                                c4 = c3 - 0x80;
                                for (b = 0; b < c4; b++)
                                {
                                    k += 1;
                                    /*fprintf ( debug , "*%2ld: %2x, %2x\n" , k , c1,c2 );*/
                                    Track_Data[i * 4 + j][k * 4 + 2] = (c1 & 0x0f);
                                    Track_Data[i * 4 + j][k * 4 + 3] = c2;
                                }
                            }
                            /*fprintf ( debug , "\n" );*/
                            continue;
                        }
                        /* end of case no Sample number nor Relative not number */

                        if (((c1 & 0x80) == 0x80) && (c1 != 0xFF) && (c1 != 0x7F))
                        {
                            c2 = in_data[Where++];
                            c3 = in_data[Where++];
                            c4 = in_data[Where++];
                            /*fprintf ( debug , "%2x, %2x, " , c2,c3);*/
                            c1 = c1 & 0x7f;
                            Track_Data[i * 4 + j][k * 4] = ((c1 << 4) & 0x10) | (poss[c1 / 2][0]);
                            Track_Data[i * 4 + j][k * 4 + 1] = poss[c1 / 2][1];
                            c6 = c2 & 0x0f;
                            if (c6 == 0x08)
                                c2 -= 0x08;
                            Track_Data[i * 4 + j][k * 4 + 2] = c2;
                            if ((c6 == 0x05) || (c6 == 0x06) || (c6 == 0x0a))
                                c3 = (c3 > 0x7f) ? ((0x100 - c3) << 4) : c3;
                            Track_Data[i * 4 + j][k * 4 + 3] = c3;
                            if (c6 == 0x0D)
                            {
                                Max = k;
                                k = l = 9999l;
                                /*fprintf ( debug , " <-- PATTERN BREAK !, track ends\n" );*/
                                continue;
                            }
                            if (c6 == 0x0B)
                            {
                                Max = k;
                                k = l = 9999l;
                                /*fprintf ( debug , " <-- PATTERN JUMP !, track ends\n" );*/
                                continue;
                            }

                            if (c4 < 0x80)
                            {
                                /*fprintf ( debug , "%2x  <--- bypass %d rows !\n" , c4 , c4 );*/
                                /*l += c4;*/
                                k += c4;
                                continue;
                            }
                            /*fprintf ( debug , "%2x  <--- repeat current row %d times\n" , c4 , c4-0x80 );*/
                            c4 = c4 - 0x80;
                            /*l += (c4-1);*/
                            for (b = 0; b < c4; b++)
                            {
                                k += 1;
                                /*fprintf ( debug , "*%2ld: %2x, %2x, %2x\n" , k , c1,c2,c3 );*/
                                Track_Data[i * 4 + j][k * 4] = ((c1 << 4) & 0x10) | (poss[c1 / 2][0]);
                                Track_Data[i * 4 + j][k * 4 + 1] = poss[c1 / 2][1];
                                c6 = c2 & 0x0f;
                                if (c6 == 0x08)
                                    c2 -= 0x08;
                                Track_Data[i * 4 + j][k * 4 + 2] = c2;
                                if ((c6 == 0x05) || (c6 == 0x06) || (c6 == 0x0a))
                                    c3 = (c3 > 0x7f) ? ((0x100 - c3) << 4) : c3;
                                Track_Data[i * 4 + j][k * 4 + 3] = c3;
                            }
                            continue;
                        }
                        if ((c1 & 0x7F) == 0x7F)
                        {
                            if ((c1 & 0x80) == 0x00)
                            {
                                /*fprintf ( debug , "  <--- bypass 1 row !\n" );*/
                                /*k += 1;*/
                                continue;
                            }
                            c2 = in_data[Where++];
                            if (c2 < 0x40)
                            {
                                /*fprintf ( debug , "%2x  <--- bypass %d rows !\n" , c2 , c2 );*/
                                k += c2;
                                continue;
                            }
                            continue;
                        }

                        c2 = in_data[Where++];
                        c3 = in_data[Where++];
                        /*fprintf ( debug , "%2x, %2x" , c2,c3 );*/
                        Track_Data[i * 4 + j][k * 4] = ((c1 << 4) & 0x10) | (poss[c1 / 2][0]);
                        Track_Data[i * 4 + j][k * 4 + 1] = poss[c1 / 2][1];
                        c6 = c2 & 0x0f;
                        if (c6 == 0x08)
                            c2 -= 0x08;
                        Track_Data[i * 4 + j][k * 4 + 2] = c2;
                        if ((c6 == 0x05) || (c6 == 0x06) || (c6 == 0x0a))
                            c3 = (c3 > 0x7f) ? ((0x100 - c3) << 4) : c3;
                        Track_Data[i * 4 + j][k * 4 + 3] = c3;
                        /*fprintf ( debug , "\n" );*/
                    }
                    Where = a;
                    /*fprintf ( debug , "\n" );*/
                    k -= 1;
                    continue;
                }

                c2 = in_data[Where++];
                c3 = in_data[Where++];
                /*fprintf ( debug , "%2x, %2x" , c2,c3 );*/
                Track_Data[i * 4 + j][k * 4] = ((c1 << 4) & 0x10) | (poss[c1 / 2][0]);
                Track_Data[i * 4 + j][k * 4 + 1] = poss[c1 / 2][1];
                c6 = c2 & 0x0f;
                if (c6 == 0x08)
                    c2 -= 0x08;
                Track_Data[i * 4 + j][k * 4 + 2] = c2;
                if ((c6 == 0x05) || (c6 == 0x06) || (c6 == 0x0a))
                    c3 = (c3 > 0x7f) ? ((0x100 - c3) << 4) : c3;
                Track_Data[i * 4 + j][k * 4 + 3] = c3;
                if (c6 == 0x0D)
                {
                    /*fprintf ( debug , " <-- PATTERN BREAK !, track ends\n" );*/
                    Max = k;
                    k = 9999l;
                    continue;
                }
                if (c6 == 0x0B)
                {
                    /*fprintf ( debug , " <-- PATTERN JUMP !, track ends\n" );*/
                    Max = k;
                    k = 9999l;
                    continue;
                }

                /*fprintf ( debug , "\n" );*/
            }
        }
    }
    /*printf ( "ok\n" );*/

    /* write pattern data */

    /*printf ( "writing pattern data ... " );*/
    for (i = 0; i < PatMax; i++)
    {
        BZERO(Whatever, 1024);
        for (j = 0; j < 64; j++)
        {
            for (k = 0; k < 4; k++)
            {
                Whatever[j * 16 + k * 4] = Track_Data[k + i * 4][j * 4];
                Whatever[j * 16 + k * 4 + 1] = Track_Data[k + i * 4][j * 4 + 1];
                Whatever[j * 16 + k * 4 + 2] = Track_Data[k + i * 4][j * 4 + 2];
                Whatever[j * 16 + k * 4 + 3] = Track_Data[k + i * 4][j * 4 + 3];
            }
        }
        fwrite(Whatever, 1024, 1, out);
    }
    free(Whatever);
    /*printf ( "ok\n" );*/


    /* read and write sample data */

    /*printf ( "writing sample data ... " );*/
    /*fprintf ( debug , "\n\nSample shit:\n" );*/
    for (i = 0; i < Nbr_Sample; i++)
    {
        Where = PW_Start_Address + Sample_Data_Address + SampleAddresses[i + 1];
        /*fprintf ( debug , "%2ld: read %-6ld at %ld\n" , i , SampleSizes[i] , ftell ( in ));*/
        SmpDataWork = (signed char*)malloc(SampleSizes[i]);
        BZERO(SmpDataWork, SampleSizes[i]);
        for (j = 0; j < SampleSizes[i]; j++) SmpDataWork[j] = in_data[Where++];
        if (GLOBAL_DELTA == ON)
        {
            c1 = 0x00;
            for (j = 1; j < SampleSizes[i]; j++)
            {
                c2 = SmpDataWork[j];
                c2 = 0x100 - c2;
                c3 = c2 + c1;
                SmpDataWork[j] = c3;
                c1 = c3;
            }
        }
        fwrite(SmpDataWork, SampleSizes[i], 1, out);
        free(SmpDataWork);
    }
    /*printf ( "ok\n" );*/

    /* crap for GLOBAL_DELTA is taken cared of elsewhere */
    if (GLOBAL_DELTA == ON)
        Crap(" The Player 6.1A  ", GOOD, BAD, out);
    else
        Crap(" The Player 6.1A  ", BAD, BAD, out);

    fclose(out);

    printf("done\n");
    return; /* useless ... but */
}